package com.landtool.lanbase.shipping;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.google.gson.Gson;
import com.landtool.lanbase.constant.CacheConsts;
import com.landtool.lanbase.database.entity.BdDataFusion;
import com.landtool.lanbase.database.entity.TargetAreaManagement;
import com.landtool.lanbase.database.entity.TgMidCountry;
import com.landtool.lanbase.database.entity.WarnBlack;
import com.landtool.lanbase.database.service.BdDataFusionService;
import com.landtool.lanbase.database.service.WarnBlackService;
import com.landtool.lanbase.entity.ShipEntity;
import com.landtool.lanbase.proto.Protocol;
import com.landtool.lanbase.utils.YmlConfigurerUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;

/**
 * 字段处理
 */
@Component
public class FormatProcess {

    private static Logger log = LoggerFactory.getLogger(FormatProcess.class);

    @Autowired
    private BdDataFusionService bdDataFusionService;

    @Autowired
    private RedisTemplate <String, Object> redisTemplate;

    @Resource
    private WarnBlackService warnBlackService;


    /**
     * 处理接口返回回来的数据
     *
     * @param result 接口返回的数据
     */
    public void getNewArray(String result) {
        //将json处理后存在list里面
        ArrayList <ShipEntity> array = new ArrayList <>();
        JSONArray shipEntityArray = new JSONArray();
        //将获取到的json字符串 转为list
        if (CacheConsts.isLogin) {
            shipEntityArray = JSONUtil.parseArray(result);
        } else {
            JSONObject json = JSONUtil.parseObj(result);
            shipEntityArray = JSONUtil.parseArray(json.get("data"));
        }

        // 排序
        shipEntityArray.sort(Comparator.comparing(obj -> ((JSONObject) obj).getInt("id")));

        for (int i = 0; i < shipEntityArray.size(); i++) {
            HashMap <String, Object> map = new HashMap <>(16);

            JSONObject shipObj = (JSONObject) shipEntityArray.get(i);
            Set <String> set = shipObj.keySet();
            Iterator <String> it = set.iterator();
            while (it.hasNext()) {
                String key = it.next();
                map.put(isAcronym(key), shipObj.get(key));
            }
            //开始处理字段
            String shipBelongKey = "sys.shipbelong_" + CacheConsts.openProvince;
            Integer shipBelong = YmlConfigurerUtil.getIntegerYmlVal(shipBelongKey);
            map.put("ship_belong", shipBelong);
            //转换成实体
            ShipEntity shipEntity = transMapToObj(map, ShipEntity.class);
            shipEntity = shipEntityDeal(shipEntity);
            boolean speed = shipEntity.getSpeed() <= 60;
            boolean mmsi = shipEntity.getMmsi() != null && shipEntity.getMmsi() == 0;

            if (speed && !mmsi) {
                array.add(shipEntity);
            }
        }

        log.info("-----处理数据完毕");

        String newKey = CacheConsts.openProvince + "_new";
        String oldKey = CacheConsts.openProvince + "_old";
        if (redisTemplate.hasKey(newKey)) {
            List <ShipEntity> list = (List <ShipEntity>) redisTemplate.opsForValue().get(newKey);
            redisTemplate.opsForValue().set(oldKey, list);
            redisTemplate.expire(newKey, 500, TimeUnit.SECONDS);
        }
        redisTemplate.opsForValue().set(newKey, array);
    }

    /**
     * @param shipEntity 原始数据
     * @return
     */
    public ShipEntity shipEntityDeal(ShipEntity shipEntity) {
        if (shipEntity.getTimestamp() == null) {
            shipEntity.setTimestamp(DateUtil.now());
        }
        if (shipEntity.getMaxlength() == null) {
            if (shipEntity.getLength() == null) {
                shipEntity.setMaxlength(0.0);
            } else {
                shipEntity.setMaxlength(shipEntity.getLength());
            }
        }
        if (shipEntity.getShip_class() == null) {
            shipEntity.setShip_class(1);
        }
        if (shipEntity.getDuration() == null) {
            shipEntity.setDuration(0.0);
        }
        if (shipEntity.getSpeed() == null) {
            shipEntity.setSpeed(0.0);
        }

        //国籍查询
        if (CacheConsts.Country != null && shipEntity.getMmsi() != null && shipEntity.getMmsi() != 0) {
            String mmsiKey = "";
            try {
                mmsiKey = shipEntity.getMmsi().toString().substring(0, 3);
                if (CacheConsts.Country.containsKey(mmsiKey)) {
                    TgMidCountry tgMidCountry = CacheConsts.Country.get(mmsiKey);
                    shipEntity.setNationality(tgMidCountry.getEnName());
                }
            } catch (IndexOutOfBoundsException e) {
                log.error("错误mmsi:" + shipEntity.getMmsi());
            }
        }
        //北斗数据融合处理
        if (CacheConsts.RecentList != null) {
            Set <String> keySet = CacheConsts.RecentList.keySet();
            String target_id = shipEntity.getShip_belong() + shipEntity.getTarget_id();
            if (keySet.contains(target_id)) {
                //先获取数据库对应的 光电最后时间
                BdDataFusion bdDataFusion = CacheConsts.RecentList.get(target_id);
                long betweenDay = DateUtil.between(bdDataFusion.getTargetLasttime(), new DateTime(), DateUnit.HOUR);
                if (betweenDay > 2) {
                    bdDataFusion.setDisable(1);
                    bdDataFusion.setTargetLasttime(new DateTime());
                    bdDataFusionService.update(bdDataFusion);
                } else {
                    bdDataFusion.setTargetLasttime(new DateTime());
                    bdDataFusionService.update(bdDataFusion);
                    //将type改为6
                    shipEntity.setShip_class(6);
                }
            }
        }
        //判断黑名单
        String warnBlackKey = CacheConsts.openProvince + "_WarnBlack";
        if (redisTemplate.hasKey(warnBlackKey) && shipEntity.getMmsi() != null) {
            Map <Object, Object> map = redisTemplate.opsForHash().entries(warnBlackKey);
            if (map.containsKey(shipEntity.getMmsi().toString())) {
                WarnBlack warnBlack = (WarnBlack) map.get(shipEntity.getMmsi().toString());
                warnBlack.setLasttime(new Date());
                warnBlackService.update(warnBlack);
            }
        }

        //判断点是否在区域里面
        String areaKey = CacheConsts.openProvince + "_targetArea";
        if (redisTemplate.hasKey(areaKey)) {
            List <TargetAreaManagement> list = (List <TargetAreaManagement>) redisTemplate.opsForValue().get(areaKey);
            for (int i = 0; i < list.size(); i++) {
                TargetAreaManagement targetArea = (TargetAreaManagement) list.get(i);
                String s = targetArea.getExtent();
                String[] scope = s.split("\\|");
                Double xmax = Double.valueOf(scope[0]);
                Double ymax = Double.valueOf(scope[1]);
                Double xmin = Double.valueOf(scope[2]);
                Double ymin = Double.valueOf(scope[3]);

                Boolean x = shipEntity.getLongitude() > xmin && shipEntity.getLongitude() < xmax;
                Boolean y = shipEntity.getLatitude() > ymin && shipEntity.getLatitude() < ymax;

                if (x && y) {
                    shipEntity.setStatic_type(targetArea.getType());
                }
            }
        }
        return shipEntity;
    }


    /**
     * 修改原始json的key值，转换为我们需要的key
     *
     * @param word
     * @return
     */
    public String isAcronym(String word) {
        switch (word) {
            case "createTime":
                word = "timestamp";
                break;
            case "type":
                word = "ship_class";
                break;
            case "id":
                word = "target_id";
                break;
            case "name":
                word = "target_name";
                break;
            case "aisLength":
                word = "aislength";
                break;
            default:
                break;
        }
        return word;
    }


    /**
     * Map转实体类
     *
     * @param map    需要初始化的数据，key字段必须与实体类的成员名字一样，否则赋值为空
     * @param entity 需要转化成的实体类
     * @return
     */
    public <T> T transMapToObj(Map <String, Object> map, Class <T> entity) {
        Gson gson = new Gson();
        String jsonStr = gson.toJson(map);
        return gson.fromJson(jsonStr, entity);
    }

    /**
     * 修改原始接口传过来的数据
     *
     * @param t
     * @return
     */
    public void getZmqNewArray(Protocol.Targets t) {
        DecimalFormat df = new DecimalFormat(".00");
        assert t != null;
        ArrayList <ShipEntity> shipEntityList = new ArrayList <>();
        for (int j = 0; j < t.getListList().size(); j++) {
            Protocol.Target a = t.getListList().get(j);
            ShipEntity shipEntity = new ShipEntity();
            Integer type = 0;
            type = getType(a, type);
            //开始处理字段
            String shipBelongKey = "sys.shipbelong_" + CacheConsts.openProvince;
            String shipBelong = YmlConfigurerUtil.getStrYmlVal(shipBelongKey);
            shipEntity.setShip_belong(shipBelong);
            shipEntity.setShip_class(type);
            shipEntity.setLength((double) a.getLength());
            shipEntity.setMaxlength((double) a.getLength());
            if (a.getMmsi() == 0) {
                shipEntity.setMmsi(null);
            } else {
                shipEntity.setMmsi(a.getMmsi());
            }

            shipEntity.setLatitude(Double.valueOf(df.format(a.getPosition().getLatitude() * 180 / Math.PI)));
            shipEntity.setLongitude(Double.valueOf(df.format(a.getPosition().getLongitude() * 180 / Math.PI)));
            shipEntity.setSpeed((double) a.getSpeed());
            shipEntity.setCourse(a.getCourse() * 180 / Math.PI);
            shipEntity.setDirection(Double.valueOf(df.format(a.getHeading() * 180 / Math.PI)));
            shipEntity.setTarget_id(a.getUid());
            shipEntity.setDisplayId(a.getId());
            // Bahamas,China,Hong Kong等
            shipEntity.setNationality(a.getExtInfoMap().get("Nationality"));
            // 船只类型，货船或者游船
            shipEntity.setShiptype(a.getExtInfoMap().get("Ship Type"));
            if (a.getExtInfoMap().get("Wide") != null) {
                shipEntity.setWide(Double.valueOf(a.getExtInfoMap().get("Wide")));
            }
            shipEntity.setAisreceiver(a.getExtInfoMap().get("AIS receiver"));
            if (a.getExtInfoMap().get("Length") != null) {
                shipEntity.setAislength(Double.valueOf(a.getExtInfoMap().get("Length")));
            }
            shipEntity.setImo(a.getExtInfoMap().get("IMO"));
            shipEntity.setCallsign(a.getExtInfoMap().get("Call_Sign"));
            StringBuilder radarKeyNum = new StringBuilder();
            Integer num = 0;
            for (String key : a.getExtInfoMap().keySet()) {
                String value = a.getExtInfoMap().get(key);
                if ("radar".equals(value)) {
                    num++;
                    radarKeyNum.append(getNumbers(key)).append(",");
                }
            }
            if (num > 0) {
                radarKeyNum = new StringBuilder(radarKeyNum.substring(0, radarKeyNum.length() - 1));
            }
            shipEntity.setRadarids(radarKeyNum.toString());
            shipEntity.setQuality((double) a.getQuality());
            shipEntity.setTimestamp(DateUtil.now());
            shipEntity = shipEntityDeal(shipEntity);
            shipEntityList.add(shipEntity);
        }
        // for循环完毕
        //加入缓存
        String newKey = CacheConsts.openProvince + "_new";
        String oldKey = CacheConsts.openProvince + "_old";
        if (redisTemplate.hasKey(newKey) != null) {
            List <ShipEntity> list = (List <ShipEntity>) redisTemplate.opsForValue().get(newKey);
            redisTemplate.opsForValue().set(oldKey, list);
            redisTemplate.expire(oldKey, 500, TimeUnit.SECONDS);
        }
        redisTemplate.opsForValue().set(newKey, shipEntityList);
        redisTemplate.expire(newKey, 500, TimeUnit.SECONDS);
        log.info("-----处理数据完毕");
    }


    /**
     * 判断雷达的类型
     *
     * @param a
     * @param type
     * @return
     */
    private Integer getType(Protocol.Target a, Integer type) {
        if (a.getType().getRadar()) {
            type = 1;
        }
        if (a.getType().getAisA()) {
            type = 2;
        }
        if (a.getType().getAisB()) {
            type = 3;
        }
        if (a.getType().getRadar() && a.getType().getAisA()) {
            type = 4;
        }
        if (a.getType().getRadar() && a.getType().getAisA()) {
            type = 5;
        }
        return type;
    }

    /**
     * 截取数字 读取字符串中第一个连续的字符串，不包含后面不连续的数字
     */
    public String getNumbers(String content) {
        Pattern pattern = Pattern.compile("\\d+");
        Matcher matcher = pattern.matcher(content);
        while (matcher.find()) {
            return matcher.group(0);
        }
        return "";
    }


}
